package org.mao.forum.service.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.mao.base.BaseServiceImpl;
import org.mao.forum.dao.ForumPostDao;
import org.mao.forum.dao.ForumPostImageDao;
import org.mao.forum.dao.ForumSectionDao;
import org.mao.forum.entity.ForumPost;
import org.mao.forum.entity.ForumPostImage;
import org.mao.forum.entity.ForumSection;
import org.mao.forum.service.ForumPostService;
import org.mao.forum.vo.ForumPostImageVo;
import org.mao.forum.vo.ForumPostVo;
import org.mao.forum.vo.ForumTaskParamsVo;
import org.mao.parser.ForumParserProxy;
import org.mao.quartz.CacheManager;
import org.mao.util.Page;
import org.mao.util.SystemConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;

@Service
@Transactional(rollbackFor = Exception.class)
public class ForumPostServiceImpl extends BaseServiceImpl<ForumPost> implements ForumPostService {

	private static Logger logger = Logger.getLogger(ForumPostServiceImpl.class);

	private static final Integer MAX_IMAGE_FILE_SIZE = 1024 * 1024 * 10;

	@Autowired
	private ForumSectionDao forumSectionDao;

	@Autowired
	private ForumPostDao forumPostDao;

	@Autowired
	private ForumPostImageDao forumPostImageDao;

	@Autowired
	private ForumParserProxy forumParserProxy;

	@Override
	public List<ForumPostVo> queryBySectionId(Integer sectionId, Page page) {
		Integer count = forumPostDao.queryCountBySectionId(sectionId);
		page.setCount(count);
		return forumPostDao.queryBySectionId(sectionId, page);
	}

	@Override
	public List<ForumPostImageVo> queryByPostId(Integer postId) {
		return forumPostImageDao.queryByPostId(postId);
	}

	@Override
	public List<Integer> queryUnFoundTorrentUrl() {
		return forumPostDao.queryUnFoundTorrentUrl();
	}
	
	@Override
	public List<Integer> queryUnFoundImage() {
		return forumPostDao.queryUnFoundImage();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void reReadTorrentUrl(Integer postId) {
		Date now = new Date();
		ForumPost forumPost = new ForumPost();
		forumPost.setId(postId);
		forumPost = forumPostDao.get(forumPost);
		Integer forumId = CacheManager.forumMap.get(forumPost.getSectionId().intValue());
		if (forumId == null) {
			ForumSection forumSection = new ForumSection();
			forumSection.setId(forumPost.getSectionId());
			forumSection = forumSectionDao.get(forumSection);
			CacheManager.forumMap.put(forumPost.getSectionId().intValue(), forumSection.getForumId());
			forumId = forumSection.getForumId();
		}
		logger.info("reReadTorrentUrl: name[" + forumPost.getName() + "]");
		forumParserProxy.reReadTorrentUrl(forumId, forumPost);
		forumPost.setUpdateTime(now);
		forumPost.setUpdateBy(-1);
		forumPostDao.update(forumPost);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void reReadImageList(Integer postId) {
		Date now = new Date();
		ForumPost forumPost = new ForumPost();
		forumPost.setId(postId);
		forumPost = forumPostDao.get(forumPost);
		Integer forumId = CacheManager.forumMap.get(forumPost.getSectionId().intValue());
		List<String> imageUrlList = forumParserProxy.reReadImageList(forumId, forumPost);
		for (String imageUrl : imageUrlList) {
			ForumPostImage forumPostImage = new ForumPostImage();
			forumPostImage.setPostId(forumPost.getId());
			forumPostImage.setHasDownload(0);
			forumPostImage.setUrl(imageUrl);
			forumPostImage.setCreateTime(now);
			forumPostImage.setCreateBy(-1);
			forumPostImageDao.insert(forumPostImage);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveImage(Integer postImageId) {
		Boolean flag = true;
		ForumPostImage forumPostImage = new ForumPostImage();
		forumPostImage.setId(postImageId);
		forumPostImage = forumPostImageDao.get(forumPostImage);
		Date now = new Date();
		forumPostImage.setUpdateTime(now);
		try {
			ForumPost forumPost = new ForumPost();
			forumPost.setId(forumPostImage.getPostId());
			forumPost = forumPostDao.get(forumPost);

			ForumSection forumSection = new ForumSection();
			forumSection.setId(forumPost.getSectionId());
			forumSection = forumSectionDao.get(forumSection);

			String savePath = SystemConfig.getInstance().getForumSavePath() + this.filterFileName(forumSection.getName()) + "/" + this.filterFileName(forumPost.getName()) + "/";
			Integer fileSize = this.saveImageFromUrl(forumPostImage.getUrl(), savePath);
			forumPostImage.setSize(fileSize / 1024);
			if (fileSize > MAX_IMAGE_FILE_SIZE) {
				forumPostImage.setHasDownload(2);
			} else {
				forumPostImage.setHasDownload(1);
			}
		} catch (Exception e) {
			logger.error("", e);
			forumPostImage.setHasDownload(2);
			flag = false;
		}
		forumPostImageDao.update(forumPostImage);
		return flag;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveTorrent(Integer postId) {
		Boolean flag = true;
		ForumPost forumPost = new ForumPost();
		forumPost.setId(postId);
		forumPost = forumPostDao.get(forumPost);
		Date now = new Date();
		forumPost.setUpdateTime(now);
		try {
			ForumSection forumSection = new ForumSection();
			forumSection.setId(forumPost.getSectionId());
			forumSection = forumSectionDao.get(forumSection);

			String savePath = SystemConfig.getInstance().getForumSavePath() + this.filterFileName(forumSection.getName()) + "/" + this.filterFileName(forumPost.getName()) + "/";
			this.saveTorrentFromUrl(forumPost.getTorrentUrl(), savePath, forumPost.getTorrentName());
			forumPost.setTorrentDownload(1);
		} catch (Exception e) {
			logger.error("", e);
			forumPost.setTorrentDownload(2);
			flag = false;
		}
		forumPostDao.update(forumPost);
		return flag;
	}

	private Integer saveImageFromUrl(String imageUrl, String savePath) throws Exception {
		InputStream is = null;
		FileOutputStream out = null;
		File file = null;
		Integer fileSize = 0;
		try {
			URL url = new URL(imageUrl);
			URLConnection conn = url.openConnection();
			conn.setConnectTimeout(1000);
			conn.setReadTimeout(1000);

			fileSize = conn.getContentLength();
			if (fileSize > MAX_IMAGE_FILE_SIZE) {
				return fileSize;
			}

			byte[] buffer = new byte[0];
			int count = 0;
			while (buffer.length == 0 || count < 10000) {
				count++;
				is = conn.getInputStream();
				buffer = new byte[is.available()];
			}

			String fileName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1, imageUrl.length());
			if (!savePath.endsWith("/")) {
				savePath += "/";
			}
			file = new File(savePath + fileName);
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			// logger.info(file.getAbsolutePath());
			if (!file.exists()) {
				file.createNewFile();
			}
			out = new FileOutputStream(file);

			int c;
			while ((c = is.read(buffer)) != -1) {
				// System.out.println("c:" + c);
				out.write(buffer, 0, c);
				// Thread.sleep(100);
			}
		} catch (IOException e) {
			throw e;
		} finally {
			if (is != null) {
				is.close();
			}
			if (out != null) {
				out.close();
			}
		}
		return fileSize;
	}

	private void saveTorrentFromUrl(String torrentUrl, String savePath, String torrentName) throws Exception {
		InputStream is = null;
		FileOutputStream out = null;
		File file = null;
		try {
			URL url = new URL(torrentUrl);
			URLConnection conn = url.openConnection();
			conn.setConnectTimeout(1000);
			conn.setReadTimeout(1000);

			byte[] buffer = new byte[0];
			int count = 0;
			while (buffer.length == 0 || count < 10000) {
				count++;
				is = conn.getInputStream();
				buffer = new byte[is.available()];
			}

			if (!savePath.endsWith("/")) {
				savePath += "/";
			}
			file = new File(savePath + torrentName);
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			if (!file.exists()) {
				file.createNewFile();
			}
			out = new FileOutputStream(file);

			int c;
			while ((c = is.read(buffer)) != -1) {
				// System.out.println("c:" + c);
				out.write(buffer, 0, c);
				// Thread.sleep(100);
			}
		} catch (IOException e) {
			throw e;
		} finally {
			if (is != null) {
				is.close();
			}
			if (out != null) {
				out.close();
			}
		}
	}

	private String filterFileName(String fileName) {
		if (StringUtils.isNotBlank(fileName)) {
			fileName = fileName.replace("\\", "");
			fileName = fileName.replace("/", "");
			fileName = fileName.replace(":", "");
			fileName = fileName.replace("*", "");
			fileName = fileName.replace("?", "");
			fileName = fileName.replace("\"", "");
			fileName = fileName.replace("<", "");
			fileName = fileName.replace(">", "");
			fileName = fileName.replace("|", "");
		}
		return fileName;
	}
}
